desc:Audio Dubler v2

options:want_all_kb
// options:no_meter

import WaveDisplayForAudioDubler v1


// -- In-out sliders ------
slider1:0<-30,6,0.01> Sound Out dB
// -- Pan section ---------
slider3:0<-100,100,0.1> Pan
slider4:1<0,1,1{ON,OFF}> -Pan Corection
// -- Detector Sliders ----
slider6:-25<-60,0,0.01> Threshold Detector dB
slider7:6<3,12,0.01> Sensitivity Detector dB
// -- Detector Double Trpping --
slider9:0<-30,12,0.01> Input Detector Gain dB
slider10:200<20,2000,1> Triger Time ms
// --- Delay Section ---------
slider12:1<0.1,30,0.1> Min Delay ms
slider13:30<0.1,30,0.1> Max Delay ms
slider14:1<0.1,30,0.1> Next Delay ms

slider16:0<0,30,0.1> Delay L CrossFade ms
slider17:0<0,30,0.1> Delay R CrossFade ms

slider20: 0<0,1,0.01> CrossFade


@init
//-- CrossFade section ---------------------------
AMP_dB = 8.68588963806504;
src_vol = tgt_vol = exp(0/AMP_DB);
src_pan = tgt_pan = 0.01*slider3;
//------------------------------------------------
ext_noinit = 1; // -- Отвечает за обновление при старт-стоп-е
envOut1 = 0;
envOut2 = 0;
retrig_cnt = 10^5;
det_velo_smpls = 1;

del_step = 1/1000*srate;

next_delay = 1; // изначальное значение дилея
n_d = 0; // локатор для смены направления прироста дилея
cf_time = 5; // время кросфейла в мс
cf_speed = 1/(cf_time/1000 * srate); // прирост за каждый сэмпл
delay_L = 0;
delay_R = 0;
pan_law = 6; // Заданно статичное значение (можно любое поставить, и отрицательное тоже)

//------------------------------------------------
attack1  = 1/1000;   //1<0.1,5,0.01>-1 attack(fast) ms
attack2  = 7/1000;   //7<2,50,0.1>-2 attack(slow) ms
release1 = 10/1000;  //10<0.1,50,0.1>-1 release ms
release2 = 15/1000;  //15<2,50,1>-2 release ms
// -- ga, gr coeff -----------
ga1 = exp(-1/(srate*attack1));
gr1 = exp(-1/(srate*release1));
ga2 = exp(-1/(srate*attack2));
gr2 = exp(-1/(srate*release2));

//-- GFX -----------------------------------------
R = 20; G = 20; B = 20;
gfx_clear = R+G*256+B*65536;
wave.Init(30,20,1015,250, 6000); // init wave - (x,y,w,h, mem_offs)

x = 0;
Trig = 0;
cf = 0;

@slider
// --- Vol Pan Section -------
tgt_vol = exp(0/AMP_DB);
tgt_pan = 0.01*slider3;
panlaw = exp(pan_law/AMP_DB);
pancomp = (panlaw > 1.0 ? 1.0/panlaw : panlaw);
// --- Delay Section ---------

// -- IN-OUT sliders - values-----------
In_gain = 10^(slider9/20);
Dry_Out = 10^(slider1/20);

// -- Detector sliders - values --------
Threshold = 10^(slider6/20);
Sensitivity = 10^(slider7/20);
Retrig = (slider10/1000)*srate;
ThresholdDraw = abs((5^(slider6/30))/1.4);


@sample

min_delay >= 29*1000/srate ? (
  min_delay = 29*1000/srate;
);

max_delay <= 1*1000/srate ? (
  max_delay = 1*1000/srate;
);

min_delay >= max_delay ? (
  slider12 = (max_delay - del_step)*1000/srate;
  sliderchange(slider12);
  min_delay = floor(slider12/1000*srate);
);

max_delay <= min_delay ? (
  slider13 = (min_delay + del_step)*1000/srate;
  sliderchange(slider13);
  max_delay = floor(slider13/1000*srate);
);

min_delay = floor(slider12/1000*srate);
max_delay = floor(slider13/1000*srate);

slider20 = x;
sliderchange(slider20);


// -- Get Input ---------------------
input = (spl0+spl1)/2 * In_gain; // channels sum
envIn = abs(input); // abs input value for enelopes etc

// -- Env followers ------------------------------
envOut1 < envIn ? ( // fast enelope
  envOut1 = envIn + ga1*(envOut1-envIn)
) : (
  envOut1 = envIn + gr1*(envOut1-envIn)
);

envOut2 < envIn ? ( // slow enelope
  envOut2 = envIn + ga2*(envOut2-envIn)
) : (
  envOut2 = envIn + gr2*(envOut2-envIn)
);

// -- Trigger ------------------------------------
retrig_cnt > Retrig ? (
  envOut1 > Threshold && envOut1/envOut2 > Sensitivity ? (
    Trig = 1;
    retrig_cnt = 0;
    trig_mrk = 1.2;
    next_delay_s = (floor(next_delay*10000/srate))/10;
    slider14 = next_delay_s;
    sliderchange(slider14);
  );
) : (
  envOut2 = envOut1; // уравнивает огибающие
  retrig_cnt+=1;
);

//  Секция выдачи рандомного дилея
next_delay >= min_delay && n_d == 0 ? (
  next_delay += 1;
  next_delay >= max_delay ? (
    // next_delay = max_delay - 2;
    n_d = 1;
  );
) : (
  next_delay -= 1;
  next_delay <= min_delay ? (
    // next_delay = min_delay + 2;
    n_d = 0;
  );
);

next_delay < min_delay || next_delay > max_delay ? ( // нужно для того: чтобы отлавливать не корректные регулировки min-max дилея
  ext_1 = floor(min_delay+(max_delay-min_delay)/2);
  next_delay = ext_1;
  n_d = 0;
);

Trig == 1 ? (
  x >= 0 && cf == 0 ? (
    x += cf_speed;
    x >= 1 ? (
      x = 1;
      cf = 1;
      delay_L = next_delay_s;
      buflL = floor(delay_L/1000*srate); // === ofset-а нет
      slider16 = delay_L;
      sliderchange(slider16);
      Trig = 0;
    );
  ):(
    x -= cf_speed;
  );
  x <= 0 ? (
    x = 0;
    cf = 0;
    delay_R = next_delay_s;
    buflR = floor(delay_R/1000*srate) + 3000; // === 3000 -ofset
    slider17 = delay_R;
    sliderchange(slider17);
    Trig = 0;
  );
);

//=========================================================
// --- Vol Pan Section -------
d_pan = (tgt_pan-src_pan)/samplesblock;
tpan = src_pan;
src_pan = tgt_pan;
tpan += d_pan;
adj = 1;

panlaw != 1.0 ? (
  panlaw > 1.0 ? adj *= panlaw;
  panatt = abs(tpan);
  adj *= pancomp+(1.0-pancomp)*(2.0/(2.0-panatt)-1.0);
);

adj0 = adj1 = adj;
tpan < 0.0 ? adj1 *= 1.0+tpan;
tpan > 0.0 ? adj0 *= 1.0-tpan;

// --- Delay Section ---------
bufLpos[0] = spl1 ;
bufLpos = bufLpos + 1 ;
bufLpos >= buflL ? bufLpos = 0;

bufRpos[0] = spl1 ;
bufRpos = bufRpos + 1 ;
bufRpos >= buflR ? bufRpos = 3000;

spl0 *= adj0;

spl1 = bufLpos[0]*sqrt(1-x) + bufRpos[0]*sqrt(x);
spl1 *= adj1;

//=======================================================

spl0*=Dry_Out;
spl1*=Dry_Out;


// == For GFX =========================================== //

wave.Build(input, trig_mrk); // args = sample input and trig velo(if>0)
trig_mrk=0;

@gfx 1084 300
//-- Draw Wave ------------------
wave.redraw ? (
  wave.Draw_waveform(ThresholdDraw); // draw
  wave.redraw = 0;      // reset redraw state
);
//-----------------------------------------

char = gfx_getchar(); // -- без него не пашет перехват mod-keys!
